package com.pmmaster.service.Impl;

import com.pmmaster.common.api.Result;
import com.pmmaster.common.entitis.FileEntity;
import com.pmmaster.common.map.UploadType;
import com.pmmaster.common.utils.StringUtil;
import com.pmmaster.core.mapper.FileMapper;
import com.pmmaster.service.FileService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @Author: Always_
 * @Date: 2020/2/10
 */
@Service
public class FileServiceImpl implements FileService {

    /**
     * 允许上传的图片类型
     */
    private static final List<String> allowed_extensions = Arrays.asList("image/jpeg", "image/jpg", "image/png", "image/gif");

    @Autowired
    private FileMapper fileMapper;

    @Override
    public Result upload(MultipartFile file, String pathPrefix, String basePath, String type) {
        // 文件真实类型
        String realType = file.getContentType().substring(file.getContentType().indexOf("/") + 1);
        String fileType = file.getOriginalFilename().substring(file.getOriginalFilename().indexOf(".") + 1);
        // 判断文件类型及大小
        if (UploadType.map.containsKey(realType)) {
            if (file.getSize() > UploadType.map.get(realType)) {
                return Result.failed("此类型文件大小不允许超过" + UploadType.map.get(realType) / 1024 / 1024 + "M");
            }
        } else {
            return Result.failed("不允许上传此类型文件");
        }
        basePath = getFolderPath(basePath + '/' + type);
        String fullPath = pathPrefix + '/' + basePath;
        //创建文件夹
        try {
            createFolder(fullPath);
        } catch (Exception e1) {
            e1.printStackTrace();
        }
        StringBuilder fileName = new StringBuilder(String.valueOf(System.currentTimeMillis()));
        String fileInfo = basePath + fileName.toString() + "." + fileType;

        while (new File(fileInfo).exists()) {
            //防重
            fileName.append(StringUtil.randomString(5));
            fileInfo = basePath + fileName.toString() + "." + fileType;
        }
        InputStream is = null;
        OutputStream os = null;
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;

        try {
            is = file.getInputStream();
            os = new FileOutputStream(new File(fileInfo));
            bis = new BufferedInputStream(is);
            bos = new BufferedOutputStream(os);

            byte buffer[] = new byte[1024];
            int len = 0;
            while ((len = bis.read(buffer)) != -1) {
                bos.write(buffer);
            }
            bos.flush();
        } catch (IOException e) {
            return Result.failed("文件上传失败：" + e.getMessage());
        } finally {
            try {
                if (bis != null) {
                    bis.close();
                }
                if (is != null) {
                    is.close();
                }
                if (bos != null) {
                    bos.close();
                }
                if (os != null) {
                    os.close();
                }
                saveUploadedFile(new FileEntity(type, file.getOriginalFilename(), realType, fileInfo, file.getSize()));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        Map<String, String> map = new HashMap<>();
        map.put("url", fileInfo);
        map.put("link", fileInfo);
        map.put("file_path", fileInfo);
        return Result.success(map);
    }

    /**
     * 上传文件入库
     *
     * @param file
     * @return
     */
    private int saveUploadedFile(FileEntity file) {
        return fileMapper.insertSelective(file);
    }

    /**
     * 处理存放地址
     *
     * @param basePath
     * @return
     */
    private String getFolderPath(String basePath) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/");
        return basePath + "/" + dateFormat.format(new Date());
    }

    /**
     * 创建文件夹，如果文件夹存在则不进行创建。
     *
     * @param path 路径
     * @throws Exception 异常
     */
    private static void createFolder(String path) throws Exception {
        path = separatorReplace(path);
        File folder = new File(path);
        if (folder.isDirectory()) {
            return;
        } else if (folder.isFile()) {
            deleteFile(path);
        }
        folder.mkdirs();
    }

    /**
     * 分隔符替换
     * window下测试通过
     *
     * @param path 路径
     * @return String 分隔符替换
     */
    private static String separatorReplace(String path) {
        return path.replace("\\", "/");
    }

    /**
     * 根据文件路径删除文件，如果路径指向的文件不存在或删除失败则抛出异常。
     *
     * @param path 路径
     * @throws Exception 异常
     */
    public static void deleteFile(String path) throws Exception {
        path = separatorReplace(path);
        File file = getFile(path);
        if (!file.delete()) {
            throw new Exception("delete file failure");
        }
    }

    /**
     * 通过路径获得文件，
     * 若不存在则抛异常，
     * 若存在则返回该文件。
     *
     * @param path 路径
     * @return File 文件
     * @throws FileNotFoundException 异常
     */
    private static File getFile(String path) throws FileNotFoundException {
        path = separatorReplace(path);
        File file = new File(path);
        if (!file.isFile()) {
            throw new FileNotFoundException("file not found!");
        }
        return file;
    }
}
